
package com.xifan.myaccount.fragments;

import android.app.Dialog;
import android.app.Fragment;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;

import com.xifan.myaccount.R;
import com.xifan.myaccount.SearchTypeActivity;
import com.xifan.myaccount.database.DatabaseImpl;
import com.xifan.myaccount.entity.Account;
import com.xifan.myaccount.entity.RecordDetail;
import com.xifan.myaccount.entity.RecordType;
import com.xifan.myaccount.util.ImageUtil;
import com.xifan.myaccount.util.SmartType;
import com.xifan.myaccount.util.UiHelper;
import com.xifan.myaccount.util.Util;
import com.xifan.myaccount.widget.MoneyView;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;

public class RecordEditor extends Fragment implements OnClickListener,
        DialogInterface.OnClickListener {
    // TODO 摇一摇

    private LayoutInflater mInflater;
    private Context mContext;

    private CheckBox mReimbursabledBox;
    private CheckBox mLocationBox;
    private Button mAccountButton;
    private Button mTypeButton;
    private TextView mDateTextView;
    private MoneyView mMoneyTextView;
    private EditText mInputText;
    private EditText mNoteText;
    private ImageButton mPhotoButton;
    private PopupWindow mNumberpad;
    private Calendar mCalendar;

    private SimpleDateFormat mDateFomatter;
    private RecordDetail mDetail;

    private int clickItem;
    private boolean isExpend;
    private String mTypeName;
    private String mLocation;
    private String mAccountName;
    private String[] mAccountArray;

    private String mPicUri = ""; // default is null
    private int mTypeId = 1;
    private int mAccountId;
    private float mTmpMoney;

    private static final int ITEM_MONEY_VIEW = 1;
    private static final int ITEM_DATE_VIEW = 2;
    private static final int ITEM_LOC_VIEW = 3;
    private static final int ITEM_ACCOUNT_VIEW = 4;

    public static final int SHOWN_TYPE_EXPEND = 1;
    public static final int SHOWN_TYPE_REVENUE = 2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int request = getArguments().getInt("opType", 1);
        mDetail = getArguments().getParcelable("detail");
        if (mDetail != null)
            mTmpMoney = mDetail.getRawMoney();
        isExpend = request == SHOWN_TYPE_EXPEND;
        setHasOptionsMenu(true);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        menu.add("confirm").setIcon(R.drawable.btn_confirm)
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getTitle().equals("confirm")) {
            if (mDetail == null)
                submit();
            else
                update();
        } else if (item.getItemId() == android.R.id.home) {
            getActivity().finish();
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mInflater = inflater;
        mContext = getActivity();
        View view = mInflater.inflate(R.layout.fragment_record_edit, null);
        mAccountButton = (Button) view.findViewById(R.id.account_spinner);
        mTypeButton = (Button) view.findViewById(R.id.type);
        mDateTextView = (TextView) view.findViewById(R.id.date);
        mMoneyTextView = (MoneyView) view.findViewById(R.id.money);
        mNoteText = (EditText) view.findViewById(R.id.note);
        mReimbursabledBox = (CheckBox) view.findViewById(R.id.reimbursable);
        mLocationBox = (CheckBox) view.findViewById(R.id.location);
        mPhotoButton = (ImageButton) view.findViewById(R.id.photo);

        mTypeButton.setOnClickListener(this);
        mAccountButton.setOnClickListener(this);

        mCalendar = Calendar.getInstance();
        mDateFomatter = Util.getDateFormatter();

        mDateTextView.setText(mDateFomatter.format(mCalendar.getTime()));
        mDateTextView.setOnClickListener(this);
        mMoneyTextView.setOnClickListener(this);
        mMoneyTextView.setTextColor(isExpend ? getResources().getColor(R.color.red_light)
                : getResources().getColor(R.color.green_light));
        mPhotoButton.setOnClickListener(this);

        mLocationBox.setOnClickListener(this);
        LoaderTask task = new LoaderTask();
        task.execute();

        initNumberpad();

        return view;
    }

    private void initNumberpad() {
        if (mNumberpad == null) {
            mNumberpad = UiHelper.createNumberPadWindow(mContext, mMoneyTextView);
            mNumberpad.setAnimationStyle(R.style.CalcAnimation);
            mNumberpad.setOutsideTouchable(false);
            mNumberpad.setFocusable(true);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.money:
                clickItem = ITEM_MONEY_VIEW;
                initNumberpad(); // make sure number isn't null
                if (!mNumberpad.isShowing()) {
                    mNumberpad.showAtLocation(v, Gravity.BOTTOM, 0, 0);
                } else {
                    mNumberpad.dismiss();
                }
                break;
            case R.id.date:
                clickItem = ITEM_DATE_VIEW;
                UiHelper.createDateDialog(mContext, mCalendar, this).show();
                break;
            case R.id.type:
                Intent intent = new Intent(mContext, SearchTypeActivity.class);
                intent.putExtra("opType", isExpend ? 1 : 2);
                startActivityForResult(intent, UiHelper.REQUEST_GET_TYPE_INFO);
                break;
            case R.id.photo:
                String[] items = !TextUtils.isEmpty(mPicUri) ? getResources()
                        .getStringArray(R.array.choose_pic_source_exists)
                        : getResources()
                                .getStringArray(R.array.choose_pic_source);
                UiHelper.createPhotoDialog(mContext, items, this).show();
                break;
            case R.id.account_spinner:
                clickItem = ITEM_ACCOUNT_VIEW;
                UiHelper.createListViewDialog(mContext, this, new OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        mAccountName = mAccountArray[position];
                    }
                }, mAccountArray, getString(R.string.add_record_account_title),
                        getString(R.string.ok), getString(R.string.cancel)).show();
                break;
            case R.id.location:
                clickItem = ITEM_LOC_VIEW;
                Toast.makeText(mContext, getText(R.string.msg_load_location),
                        Toast.LENGTH_SHORT).show();
                new ConnectTask().execute();
                break;
        }

    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        switch (which) {
            case Dialog.BUTTON_POSITIVE:
                switch (clickItem) {
                    case ITEM_MONEY_VIEW:
                        mMoneyTextView.setText(mInputText.getText().toString());
                        break;
                    case ITEM_DATE_VIEW:
                        mDateTextView.setText(mDateFomatter.format(mCalendar.getTime()));
                        break;
                    case ITEM_LOC_VIEW:
                        mLocationBox.setChecked(TextUtils.isEmpty(mLocation) ? false : true);
                        Toast.makeText(
                                mContext,
                                TextUtils.isEmpty(mLocation) ? getString(R.string.msg_no_location)
                                        : getString(R.string.msg_location) + mLocation,
                                Toast.LENGTH_SHORT).show();
                        break;
                    case ITEM_ACCOUNT_VIEW:
                        mAccountButton.setText(mAccountName);
                }
                break;
            case Dialog.BUTTON_NEGATIVE:
                dialog.cancel();
                if (clickItem == ITEM_LOC_VIEW) {
                    mLocation = null;
                    mLocationBox.setChecked(false);
                }
                break;
            case UiHelper.REQUEST_SELECT_CAMERA:
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                File file = ImageUtil.getDefaultPicPath();
                mPicUri = file.getPath();
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
                startActivityForResult(intent, UiHelper.REQUEST_SELECT_CAMERA);
                break;
            case UiHelper.REQUEST_SELECT_PICTURE:
                Intent i = new Intent(Intent.ACTION_PICK,
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(i, UiHelper.REQUEST_SELECT_PICTURE);
                break;
            case UiHelper.REQUEST_SELECT_NONE:
                mPicUri = null;
                mPhotoButton.setImageDrawable(getResources().getDrawable(
                        R.drawable.ic_add_record_photos_empty));
                break;

        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == -1) {
            if (requestCode == UiHelper.REQUEST_SELECT_PICTURE) {
                File file = ImageUtil.getDefaultPicPath();
                mPicUri = file.getPath();
                Bitmap bitmap = ImageUtil.getPicFromAlbum(mContext, file, data.getData());
                bitmap.recycle(); // recycle it for no further use.
                mPhotoButton.setImageDrawable(getResources().getDrawable(
                        R.drawable.ic_add_record_photos));
            } else if (requestCode == UiHelper.REQUEST_SELECT_CAMERA) {
                Bitmap bitmap = ImageUtil.getPicFromCamera(mContext, new File(mPicUri));
                bitmap.recycle(); // recycle it for no further use.
                mPhotoButton.setImageDrawable(getResources().getDrawable(
                        R.drawable.ic_add_record_photos));
            } else {
                mTypeId = data.getIntExtra("typeId", 1);
                mTypeName = data.getStringExtra("typeName");
                mTypeButton.setText(mTypeName);
            }
        } else if (requestCode == UiHelper.REQUEST_SELECT_PICTURE
                || requestCode == UiHelper.REQUEST_SELECT_CAMERA) {
            Toast.makeText(mContext,
                    getResources().getString(R.string.show_record_choose_pic_failed),
                    Toast.LENGTH_SHORT).show();
            mPhotoButton.setImageDrawable(getResources().getDrawable(
                    R.drawable.ic_add_record_photos_empty));
        }
    }

    private class LoaderTask extends AsyncTask<Void, Void, HashMap<String, Object>> {

        @Override
        protected HashMap<String, Object> doInBackground(Void... params) {
            List<Account> account = SmartType.getAccountList();
            List<String> types = SmartType.getAccountTypeList();
            List<RecordType> typeList = SmartType.getMatch(isExpend ? 1 : 2);
            String[] list = new String[account.size()];

            for (int i = 0, size = account.size(); i < size; i++) {
                Account ac = account.get(i);
                boolean hasName = !TextUtils.isEmpty(ac.getAccountName());
                list[i] = hasName ? ac.getAccountName() : types.get(ac.getAccountType());
            }

            HashMap<String, Object> map = new HashMap<String, Object>();
            map.put("accountlist", account);
            map.put("accounttypelist", types);

            if (mDetail == null && TextUtils.isEmpty(mTypeName)) {
                map.put("type", typeList.get(0));
            } else {
                for (int i = 0, size = typeList.size(); i < size; i++) {
                    RecordType info = typeList.get(i);
                    if (info.typeId == mDetail.getRecordType()) {
                        map.put("type", info);
                    }
                }
            }
            return map;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void onPostExecute(HashMap<String, Object> result) {
            super.onPostExecute(result);

            List<Account> account = (List<Account>) result.get("accountlist");
            List<String> types = (List<String>) result.get("accounttypelist");

            RecordType type = (RecordType) result.get("type");
            mTypeId = type.typeId;
            mTypeName = type.typeName;
            mTypeButton.setText(type.typeName);

            mAccountId = mDetail == null ? Account.DEFAULT_ACCOUNT_ID : mDetail.getAccountId();
            for (int i = 0, size = account.size(); i < size; i++) {
                Account ac = account.get(i);

                if (ac.getId() == mAccountId) {
                    boolean hasName = !TextUtils.isEmpty(ac.getAccountName());
                    mAccountName = hasName ? ac.getAccountName() : types.get(ac
                            .getAccountType());
                }
            }
            mAccountButton.setText(mAccountName);

            if (mDetail != null) {
                mPicUri = mDetail.getPicUri();
                mPhotoButton.setImageDrawable(getResources().getDrawable(
                        TextUtils.isEmpty(mPicUri) ?
                                R.drawable.ic_add_record_photos_empty
                                : R.drawable.ic_add_record_photos));
                mLocation = mDetail.getLocation();
                mLocationBox.setChecked(TextUtils.isEmpty(mLocation) ? false : true);
                mNoteText.setText(mDetail.getNote());
                mMoneyTextView.setText(mDetail.getMoney());
                mDateTextView.setText(mDetail.getDate());
            }

        }
    }

    private class ConnectTask extends AsyncTask<Void, Void, String[]> {

        @Override
        protected String[] doInBackground(Void... params) {
            return Util.getLocationList(mContext);
        }

        @Override
        protected void onPostExecute(final String[] result) {
            super.onPostExecute(result);
            UiHelper.createListViewDialog(mContext, RecordEditor.this, new OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Log.e("xifan", "selected");
                    mLocation = result[position];
                    view.setSelected(true);

                }
            }, result, getString(R.string.location), getString(R.string.ok),
                    getString(R.string.location_delete)).show();
            mLocationBox.setChecked(TextUtils.isEmpty(mLocation) ? false : true);
        }
    }

    private void update() {
        RecordDetail detail = mDetail;
        if (detail != null) {
            setDetail(detail);
        } else {
            Log.e("xifan", "update error: detail is null");
            return;
        }
        try {
            DatabaseImpl db = new DatabaseImpl(mContext, true);
            ContentValues cv = new ContentValues();
            cv.put("accountId", detail.getAccountId());
            cv.put("recordOp", getOpeateInt(isExpend));
            cv.put("recordType", detail.getRecordType());
            cv.put("moneyAmount", detail.getRawMoney());
            cv.put("picUri", detail.getPicUri());
            cv.put("recordDate", detail.getDate());
            cv.put("location", detail.getLocation());
            cv.put("note", detail.getNote());
            cv.put("isReimbursabled", detail.isReimbursabled());
            db.doUpdate("detail", cv, "id=?", new String[] {
                    String.valueOf(detail.getId())
            });
            float count = detail.getRawMoney() - mTmpMoney;
            db.syncAccount(count, detail.getRecordType(), detail.getAccountId(),
                    getOpeateInt(isExpend));
            db.close();
            Log.e("xifan", "update done");
            getActivity().setResult(-1, new Intent().putExtra("detail", detail));
            getActivity().finish();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void submit() {
        RecordDetail detail = mDetail == null ? new RecordDetail() : mDetail;
        setDetail(detail);

        try {
            DatabaseImpl db = new DatabaseImpl(mContext, true);
            ContentValues cv = new ContentValues();
            cv.put("accountId", detail.getAccountId());
            cv.put("recordOp", getOpeateInt(isExpend));
            cv.put("recordType", detail.getRecordType());
            cv.put("moneyAmount", detail.getRawMoney());
            cv.put("picUri", detail.getPicUri());
            cv.put("recordDate", detail.getDate());
            cv.put("location", detail.getLocation());
            cv.put("note", detail.getNote());
            cv.put("isReimbursabled", detail.isReimbursabled());
            db.doInsert("detail", cv);
            db.syncAccount(detail.getRawMoney(), detail.getRecordType(),
                    detail.getAccountId(),
                    getOpeateInt(isExpend));
            db.close();
            Log.e("xifan", "submit done");
            getActivity().setResult(-1);
            getActivity().finish();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setDetail(RecordDetail detail) {
        detail.setAccountId(mAccountId);
        detail.setDate(mDetail == null ? mDateFomatter.format(mCalendar.getTime()) : mDetail
                .getDate());
        detail.setMoney(Float.parseFloat(mMoneyTextView.getText()));
        detail.setNote(mNoteText.getText().toString());
        detail.setPicUri(mPicUri);
        detail.setRecordType(mTypeId);
        detail.setOperateType(getOpeateInt(isExpend));
        detail.setState(0);
        detail.setReimbursabled(mReimbursabledBox.isChecked() ? 1 : 0);
        if (mLocationBox.isChecked()) {
            detail.setLocation(mLocation);
        }
    }

    private int getOpeateInt(boolean val) {
        return isExpend ? 1 : 2;
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mNumberpad != null) {
            mNumberpad.dismiss();
            mNumberpad = null;
        }
    }

}
